
#include <mem_matrix.h>
#include <gtest/gtest.h>
	
	
int main(int argc, char **argv)
{
 	testing::InitGoogleTest(&argc, argv);
	return RUN_ALL_TESTS();
}
 
/**
 * @brief 
**/
class test_mem_matrix_t_mem_matrix_t_suite : public ::testing::Test
{
protected:
	test_mem_matrix_t_mem_matrix_t_suite(){};
	virtual ~test_mem_matrix_t_mem_matrix_t_suite(){};
	virtual void SetUp()
	{
		//Called befor every TEST_F(test_mem_matrix_t_mem_matrix_t_suite, *)
	};
	virtual void TearDown()
	{
		//Called after every TEST_F(test_mem_matrix_t_mem_matrix_t_suite, *)
	};
};
 
/**
 * @brief 
 * @begin_version 
**/
TEST_F(test_mem_matrix_t_mem_matrix_t_suite, case_name1)
{
	//TODO
}
 
/**
 * @brief 
 * @begin_version 
**/
TEST_F(test_mem_matrix_t_mem_matrix_t_suite, case_name2)
{
	//TODO
}
 
/**
 * @brief 
**/
class test_mem_matrix_t_create_suite : public ::testing::Test
{
protected:
	test_mem_matrix_t_create_suite(){};
	virtual ~test_mem_matrix_t_create_suite(){};
	virtual void SetUp()
	{
		//Called befor every TEST_F(test_mem_matrix_t_create_suite, *)
	};
	virtual void TearDown()
	{
		//Called after every TEST_F(test_mem_matrix_t_create_suite, *)
	};
	mem_matrix_t mem_matrix;
};
 
/**
 * @brief 
 * @begin_version 
**/
TEST_F(test_mem_matrix_t_create_suite, case_name1)
{
	int ret = mem_matrix.create();
	EXPECT_EQ(0, ret);
}
 
/**
 * @brief 
**/
class test_mem_matrix_t_insert_suite : public ::testing::Test
{
protected:
	test_mem_matrix_t_insert_suite(){};
	virtual ~test_mem_matrix_t_insert_suite(){};
	virtual void SetUp()
	{
		mem_matrix.create();
	};
	virtual void TearDown() {
		//Called after every TEST_F(test_mem_matrix_t_insert_suite, *)
	};
	mem_matrix_t mem_matrix;
};
 
/**
 * @brief 
 * @begin_version 
**/
TEST_F(test_mem_matrix_t_insert_suite, insert_random)
{
	mem_matrix_t mem_matrix(bytes_t::uint64_comparator, bytes_t::uint64_comparator);
	int ret = mem_matrix.create();
	EXPECT_EQ(0, ret);

	for(uint32_t i = 0; i < 10; i++)
	{
		pitem p(new item_t);
		uint32_t n = rand()%10;
		p->col = n;
		p->row = n+1;
		p->value = n+2;
		int ret = mem_matrix.insert(p);
		EXPECT_EQ(0,ret);

		// print it.
		pnode node = mem_matrix._head->nexts[0];
		while(node)
		{
			uint64_t row = (uint64_t)node->item->row;
			uint64_t col = (uint64_t)node->item->col;
			uint64_t timestamp = node->item->timestamp;
			uint64_t value = (uint64_t)node->item->value;
			cout << row << "," << col << "," << timestamp << "," << value << "\t";
			node = node->nexts[0];
		}
		cout << endl;
	}

}

TEST_F(test_mem_matrix_t_insert_suite, insert_eq_item)
{
	mem_matrix_t mem_matrix(bytes_t::uint64_comparator, bytes_t::uint64_comparator);
	int ret = mem_matrix.create();
	EXPECT_EQ(0, ret);

	for(uint32_t i = 0; i < 10; i++)
	{
		pitem p(new item_t);
		p->col = 1;
		p->row = 2;
		p->value = i;
		int ret = mem_matrix.insert(p);
		EXPECT_EQ(0,ret);

		// print it.
		pnode node = mem_matrix._head->nexts[0];
		while(node)
		{
			uint64_t row = (uint64_t)(node->item->row);
			uint64_t col = (uint64_t)(node->item->col);
			uint64_t timestamp = node->item->timestamp;
			uint64_t value = (uint64_t)(node->item->value);
			cout << row << "," << col << "," << timestamp << "," << value << "\t";
			node = node->nexts[0];
		}
		cout << endl;
	}

}
 
/**
 * @brief
**/
class test_mem_matrix_t_find_suite : public ::testing::Test
{
protected:
	test_mem_matrix_t_find_suite(){};
	virtual ~test_mem_matrix_t_find_suite(){};
	virtual void SetUp()
	{
	};
	virtual void TearDown()
	{
		//Called after every TEST_F(test_mem_matrix_t_find_suite, *)
	};
};
 
TEST_F(test_mem_matrix_t_find_suite, find_in_multi_eq_row_matrix)
{
	mem_matrix_t mem_matrix(bytes_t::uint64_comparator, bytes_t::uint64_comparator);
	mem_matrix.create();

	for(uint32_t i = 0; i < 10; i++)
	{
		pitem p(new item_t);
		p->row = 1;
		p->col = i;
		p->value = i + 1;
		int ret = mem_matrix.insert(p);
		EXPECT_EQ(0,ret);
	}

	bytes_t row(1);
	std::vector<pitem> res;
	int ret = mem_matrix.find(row, res);
	EXPECT_EQ(0,ret);
	EXPECT_EQ(10,res.size());
	int i = 0;
	for(uint32_t i = 0; i < res.size(); i++)
	{
		uint64_t row = (uint64_t)(res[i]->row);
		uint64_t col = (uint64_t)(res[i]->col);
		uint64_t value = (uint64_t)(res[i]->value);
		EXPECT_EQ(1, row);
		EXPECT_EQ(i, col);
		EXPECT_EQ(i+1, value);
		i++;
		cout << row << "," << col << "," << value << "\t";
	}
	cout << endl;
}

TEST_F(test_mem_matrix_t_find_suite, find_in_multi_eq_item_matrix)
{
	mem_matrix_t mem_matrix(bytes_t::uint64_comparator, bytes_t::uint64_comparator);
	mem_matrix.create();

	for(uint32_t i = 0; i < 10; i++)
	{
		pitem p(new item_t);
		p->row = 1;
		p->col = 2;
		p->value = i;
		int ret = mem_matrix.insert(p);
		EXPECT_EQ(0,ret);
	}

	bytes_t row(1);
	std::vector<pitem> res;
	int ret = mem_matrix.find(row, res);
	EXPECT_EQ(0,ret);
	EXPECT_EQ(1, res.size());
	int i = 0;
	for(uint32_t i = 0; i < res.size(); i++)
	{
		uint64_t row = (uint64_t)(res[i]->row);
		uint64_t col = (uint64_t)(res[i]->col);
		uint64_t value = (uint64_t)(res[i]->value);
		EXPECT_EQ(1, row);
		EXPECT_EQ(2, col);
		EXPECT_EQ(9, value);
		i++;
		cout << row << "," << col << "," << value << "\t";
	}
	cout << endl;
}

TEST_F(test_mem_matrix_t_find_suite, find_in_empty_matrix)
{
	mem_matrix_t mem_matrix(bytes_t::uint64_comparator, bytes_t::uint64_comparator);
	mem_matrix.create();

	bytes_t row(4);
	std::vector<pitem> res;
	int ret = mem_matrix.find(row, res);
	EXPECT_EQ(-1,ret);
	for(uint32_t i = 0; i < res.size(); i++)
	{
		uint64_t row = (uint64_t)(res[i]->row);
		uint64_t col = (uint64_t)(res[i]->col);
		uint64_t timestamp = res[i]->timestamp;
		uint64_t value = (uint64_t)(res[i]->value);
		cout << row << "," << col << "," << timestamp << "," << value << "\t";
	}
	cout << endl;
}

/**
 * @brief
**/
class test_mem_matrix_iterator_t_suite : public ::testing::Test
{
protected:
	test_mem_matrix_iterator_t_suite(){};
	virtual ~test_mem_matrix_iterator_t_suite(){};
	virtual void SetUp()
	{
	};
	virtual void TearDown()
	{
	};
};

TEST_F(test_mem_matrix_iterator_t_suite, iterate_empty_mem_matrix)
{
	mem_matrix_t mem_matrix(bytes_t::uint64_comparator, bytes_t::uint64_comparator);
	mem_matrix.create();

	mem_matrix_iterator_t ite(mem_matrix);
	int ret = ite.reset();
	EXPECT_EQ(0, ret);
	EXPECT_EQ(0, ite.size());
	pitem item;
	int i = 0;
	while(0 == ite.get_next(item))
	{
		cout << (uint64_t)item->row << "," << (uint64_t)item->col << ","
				<< (uint64_t)item->value << "\t";
		i++;
	}
	cout << endl;
	EXPECT_EQ(0,i);
}

TEST_F(test_mem_matrix_iterator_t_suite, iterate_multi_eq_item_matrix)
{
	mem_matrix_t mem_matrix(bytes_t::uint64_comparator, bytes_t::uint64_comparator);
	mem_matrix.create();

	for(uint32_t i = 0; i < 10; i++)
	{
		pitem p(new item_t);
		p->row = 1;
		p->col = 2;
		p->value = i;
		int ret = mem_matrix.insert(p);
		EXPECT_EQ(0,ret);
	}

	// print it.
	pnode node = mem_matrix._head->nexts[0];
	while(node)
	{
		uint64_t row = (uint64_t)(node->item->row);
		uint64_t col = (uint64_t)(node->item->col);
		uint64_t value = (uint64_t)(node->item->value);
		cout << row << "," << col << "," << value << "\t";
		node = node->nexts[0];
	}
	cout << endl;

	mem_matrix_iterator_t ite(mem_matrix);
	int ret = ite.reset();
	EXPECT_EQ(0, ret);
	pitem item;
	int i = 0;
	while(0 == ite.get_next(item))
	{
		uint64_t row = (uint64_t)item->row;
		uint64_t col = (uint64_t)item->col;
		uint64_t value = (uint64_t)item->value;
		EXPECT_EQ(1, row);
		EXPECT_EQ(2, col);
		EXPECT_EQ(9, value);
		i++;
		cout << row << "," << col << "," << value << "\t";
	}
	cout << endl;
	EXPECT_EQ(1, i);
}

TEST_F(test_mem_matrix_iterator_t_suite, iterate_multi_eq_row_matrix)
{
	mem_matrix_t mem_matrix(bytes_t::uint64_comparator, bytes_t::uint64_comparator);
	mem_matrix.create();

	for(uint32_t i = 0; i < 10; i++)
	{
		pitem p(new item_t);
		p->row = 1;
		p->col = i;
		p->value = i+1;
		int ret = mem_matrix.insert(p);
		EXPECT_EQ(0,ret);
	}

	// print it.
	pnode node = mem_matrix._head->nexts[0];
	while(node)
	{
		uint64_t row = (uint64_t)(node->item->row);
		uint64_t col = (uint64_t)(node->item->col);
		uint64_t value = (uint64_t)(node->item->value);
		cout << row << "," << col << "," << value << "\t";
		node = node->nexts[0];
	}
	cout << endl;

	mem_matrix_iterator_t ite(mem_matrix);
	int ret = ite.reset();
	EXPECT_EQ(0, ret);
	pitem item;
	int i = 0;
	while(0 == ite.get_next(item))
	{
		uint64_t row = (uint64_t)item->row;
		uint64_t col = (uint64_t)item->col;
		uint64_t value = (uint64_t)item->value;
		EXPECT_EQ(1, row);
		EXPECT_EQ(i, col);
		EXPECT_EQ(i+1, value);
		i++;
		cout << row << "," << col << "," << value << "\t";
	}
	cout << endl;
	EXPECT_EQ(10, i);
}


 
